package com.michael.demos.base.thread.juc.lock;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * 类功能描述:
 * <pre>
 *   AbstractQueuedSynchronizer 注释中的用例 —— 类CountDownLatch实现
 * </pre>
 *
 * @author Michael
 * @version 1.0
 * @date 2020/8/13 16:22
 */
public class BooleanLatchMain {

	public static void main(String[] args) throws InterruptedException {

		// 学生数量
		int countStu = 10;
		// 空余座位
		BooleanLatch freeSeat = new BooleanLatch(countStu);

		System.out.println("上课铃声响起...老师准备讲课");

		ExecutorService threadPool = Executors.newFixedThreadPool(countStu);

		for (int i = 0; i < countStu; i++) {
			int index = i;
			threadPool.submit(() -> {
				try {
					TimeUnit.MILLISECONDS.sleep(getRandomInt(1000, 5000));
					System.out.println("第" + index + "个准备好了");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				freeSeat.countDown();
			});
		}

		// 所有学生在座位坐好了再讲课
		freeSeat.await();
		System.out.println("所有同学都坐好了，老师开始讲课");
		threadPool.shutdown();
	}

	private static int getRandomInt(int min, int max) {
		Random random = new Random();
		return min + random.nextInt((max - min) + 1);
	}

}

/**
 * 类功能描述:
 * <pre>
 *   AbstractQueuedSynchronizer 注释中的用例 —— 类CountDownLatch实现
 * </pre>
 *
 * @author Michael
 * @version 1.0
 * @date 2020/8/13 15:12
 */
class BooleanLatch {

	private final Sync sync;

	public BooleanLatch(int count) {
		sync = new Sync(count);
	}

	public boolean isSignalled() {
		return sync.isSignalled();
	}

	public void countDown() {
		sync.releaseShared(1);
	}

	public void await() throws InterruptedException {
		sync.acquireSharedInterruptibly(1);
	}

	private static class Sync extends AbstractQueuedSynchronizer {

		boolean isSignalled() {
			return getState() != 0;
		}

		public Sync(int count) {
			setState(count);
		}

		@Override
		protected int tryAcquireShared(int ignore) {
			return isSignalled() ? -1 : 1;
		}

		@Override
		protected boolean tryReleaseShared(int ignore) {
			while (true) {
				int currentState = getState();
				if (currentState == 0) {
					return false;
				}
				int nextState = currentState - 1;
				if (compareAndSetState(currentState, nextState)) {
					return nextState == 0;
				}
			}
		}

	}
}
